using System;
using System.Drawing;

namespace Nate.Shared
{
    public class Manager
    {
        #region Public Methods and Data
        public Manager()
        {
            _blackboard = new Blackboard();
            _options_algo = "";
        }

        public Blackboard.Pathing PathingBB
        {
            get
            {
                return _blackboard.PathingBB;
            }
        }

        // Update
        //  Returns "true" if the system found enough information in the given
        //  GuiBB to activate the pathfinder. All information about the current
        //  state of the pathfinding process is in the PathingBB.
        public bool Update(Blackboard.GUI GuiBB)
        {
            // Grab the options data ASAP. Do this by constructing the object
            // early to get its options data.

            if (null == _algorithm &&
                null != GuiBB.AlgorithmName && 
                GuiBB.AlgorithmName.Length > 0 &&
                null == _blackboard.PathingBB.Options)
            {
                Pathfinding.IPathfind temp = Utils.Create(GuiBB.AlgorithmName);
                if (null != temp)
                {
                    _blackboard.PathingBB.Options = temp.Options;
                    _options_algo = GuiBB.AlgorithmName;
                }
            }

            // Don't even start pathing if the caller hasn't filled in all the
            // requied data

            if (!GuiBB.ReadyForPathing)
            {
                if (_options_algo.Length > 0 &&
                    _options_algo != GuiBB.AlgorithmName)
                {
                    _options_algo = "";
                    _blackboard.PathingBB.Options = null;
                }

                return false;
            }

            // If any of the data that gui code maintains has changed since the
            // last update restart the pathing code.

            if (GuiBB != _blackboard.GuiBB)
            {
                _Init(GuiBB);
            }

            if (null == _algorithm)
            {
                return false;
            }

            _blackboard.PathingBB.Status = _algorithm.Tick();
            _blackboard.PathingBB.Path   = _algorithm.Path;
            _blackboard.PathingBB.Options = _algorithm.Options;
            _options_algo = GuiBB.AlgorithmName;
            return true;
        }
        #endregion

        #region Private Methods

        public void _Init(Blackboard.GUI GuiBB)
        {
            _algorithm  = null;
            _blackboard = new Blackboard(GuiBB);
            
            _algorithm  = Utils.Create(_blackboard.GuiBB.AlgorithmName);
            if (null == _algorithm)
            {
                return;
            }

            try
            {
                Shared.BitmapToGraph bmp2graph = new BitmapToGraph(_blackboard.GuiBB.Bmp, Color.Black, _blackboard.GuiBB.AllowDiagonals, _blackboard.GuiBB.AllowVariable);
                Pathfinding.Graph graph = new Pathfinding.Graph(bmp2graph.GraphNodes);

                Pathfinding.NodeID start_id = graph.FindNodeID(_blackboard.GuiBB.Start);
                Pathfinding.NodeID dest_id = graph.FindNodeID(_blackboard.GuiBB.Dest);

                _algorithm.OptionSelection = _blackboard.GuiBB.SelectedOption;
                _algorithm.Init(start_id, dest_id, graph);
            }
            catch (Pathfinding.Graph.Exception.NotInGraph )
            {
                NUtils.Console.Error("Either the destination or start point is at an unreachable location.");
                _algorithm = null;
                return;
            }

        }

        #endregion

        #region Private Data

        private Blackboard              _blackboard;
        private Pathfinding.IPathfind   _algorithm;
        private string                  _options_algo;
        
        #endregion
    }
}